#include <uv.h>
#include <stdio.h>

uv_loop_t *loop;
uv_tcp_t server;

void on_new_connection(uv_stream_t *server, int status) {
    if (status < 0) {
        fprintf(stderr, "Error on_new_connection: %s\n", uv_strerror(status));
        return;
    }

    uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
    uv_tcp_init(loop, client);

    if (uv_accept(server, (uv_stream_t*) client) == 0) {
        printf("Client connected\n");

        uv_read_start((uv_stream_t*) client, 
            [](uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
                buf->base = (char*) malloc(suggested_size);
                buf->len = suggested_size;
            },
            [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
                if (nread > 0) {
                    printf("Received message from client: %.*s\n", (int)nread, buf->base);
                } else if (nread < 0) {
                    fprintf(stderr, "Error on_read: %s\n", uv_strerror(nread));
                    uv_close((uv_handle_t*) stream, nullptr);
                }

                free(buf->base);
            }
        );
    } else {
        uv_close((uv_handle_t*) client, nullptr);
    }
}

int main() {
    loop = uv_default_loop();

    uv_tcp_init(loop, &server);

    struct sockaddr_in bind_addr;
    uv_ip4_addr("0.0.0.0", 8888, &bind_addr);

    uv_tcp_bind(&server, (const struct sockaddr*)&bind_addr, 0);

    int r = uv_listen((uv_stream_t*) &server, 128, on_new_connection);
    if (r) {
        fprintf(stderr, "Error uv_listen: %s\n", uv_strerror(r));
        return 1;
    }

    printf("Server running on port 8888\n");

    return uv_run(loop, UV_RUN_DEFAULT);
}
